
local setmetatable = setmetatable
local assert = assert
local ipairs = ipairs

local luasql = require("luasql.sqlite3")
local iconv = require("iconv")
local string = require("string")

--just for test
require("std")
local print = print

module("contactsdb")

contactsdb={}

function contactsdb:new(o)
    --{db_path="db_path"}
    o = o or {}
    
    --set class
    setmetatable(o, self)
    self.__index = self
    
    self.load_cache(o)
    
    return o
end

function contactsdb:replace_cache(contacts)
    self.cache = contacts
    self:save_cache()
end

function contactsdb:load_cache()
    ---- if db exist,import the cache
    -- create environment object
    local env = assert (luasql.sqlite3())
    -- connect to data source
    --print(self)
    local con = assert (env:connect(self.db_path))
    -- check if contacts table exists
    local cur = con:execute('select * from sqlite_master where tbl_name = "contacts"')
    --cur will alway not nil,so we need to get a row to judge
    local row = cur:fetch ({}, "a")
    if (row~=nil) then
        cur = assert (con:execute"SELECT name, number from contacts")
        
        local cd = iconv.new("UTF-16BE" .. "//TRANSLIT", "UTF-8")
        
        self.cache = {}
        
        local row = cur:fetch ({}, "a")
        while row do
            row.name_ucs2 = cd:iconv(row.name)
            row.name = nil
            self.cache[#self.cache+1] = row
            row = {}
            row = cur:fetch (row, "a") -- reusing the table of results
        end
    end
end

function contactsdb:cache_defaultenc(defaultenc)
    local cd = iconv.new(defaultenc .. "//TRANSLIT", "UTF-16BE")
    for i = 1,#self.cache do
        self.cache[i].name_defaultenc = cd:iconv(self.cache[i].name_ucs2)
        --print(self.cache[i].name_defaultenc)
    end
end

function contactsdb:save_cache()
    if self.cache==nil then return end
    
    -- create environment object
    local env = assert (luasql.sqlite3())
    -- connect to data source
    local con = assert (env:connect(self.db_path))
    
    local res
    res = con:execute"DROP TABLE contacts"
    res = assert (con:execute[[
      CREATE TABLE contacts(
        name  varchar(50),
        number varchar(50)
      )
    ]])
    
    local cd = iconv.new("UTF-8" .. "//TRANSLIT", "UTF-16BE")
    local name_utf8, err ,num
    
    
    for i, c in ipairs (self.cache) do
        name_utf8, err = cd:iconv(c.name_ucs2)
        number = c.number or ""
        res = assert (con:execute(string.format([[
            INSERT INTO contacts
            VALUES ('%s', '%s')]], name_utf8, number)
        ))
    end
end

function contactsdb:search_cache(s)
    local t = {}
    
    if (s==nil or s=="") then
        for i = 1,#self.cache do
            local c = self.cache[i]
            t[#t+1]=string.format('"%s" %s',c.name_defaultenc,c.number)
        end
        return t
    end
    
    local c
    for i = 1,#self.cache do
        local c = self.cache[i]
        if (c.name_defaultenc:find(s)~=nil or c.number:find(s)~=nil) then
            t[#t+1]=string.format('"%s" %s',c.name_defaultenc,c.number)
        end
    end
    --print(t)
    return t
end
